Welcome back.
In this lecture.
We're going to now start working on the shop section of our GUI by adding game passes and implementing
those game passes in our scripts.
If you remember inside of our starting menu GUI, let me go ahead and enable UI visibility.
We had a store frame and inside of here there are two game passes that I would like our players to buy.
We're going to have one game pass, which will give players an upgraded golden knife that they will
spawn with to deal more damage to zombies, and then the other game pass is going to be a faster reload
speed for all of their guns.
So we're going to have to script on the client when they press these buy buttons to let the server know,
hey, we want to purchase this particular Game Pass.
The server is going to prompt them to purchase it, and if they purchase the Game Pass, then we're
going to give them the benefits associated with that game Pass.
We're also going to check for when players join our game, see if they already own these game passes,
and if they do, we'll give them those benefits.
So let me go ahead and re hide this and disable UI visibility.
And back in the creator dashboard, we can go ahead and create a game pass for our game.
I'm back inside of my wave game, and we can head to the monetization tab, and there's a section for
Game Passes.
And inside of here I haven't created any, but we're going to create a new Game Pass.
I'm going to name this game Pass My Golden Knife, and I'll just give it a brief description of like.
This pass will give you access to an upgraded golden knife that deals more damage to zombies.
We'll say something like that, and then we can also go ahead and add an image for your Game pass as
well.
So I just added a very basic image.
It doesn't really matter.
You can add whatever image you would like for your game pass, but then once you're done with that,
we can go ahead and hit Create Pass.
And then once we're done with that, we want to go ahead and actually select this game pass.
And then we want to go to the sales section.
And then we want to mark it as for sale.
And then you can go ahead and set a price in here.
Make sure it's a reasonable price.
I'm just going to set mine to 99 Robux.
We'll hit save changes.
And now what we can go ahead and do is get the asset ID for this Game Pass.
We'll copy that.
And now back inside of studio, I'm going to go ahead and duplicate the badge enum.
And instead I'm going to call this one my Game Pass enum.
And inside of my Game Pass enum, I'm going to delete this, but instead replace it with all the game
passes that can be purchased.
For example, our Knife game pass.
I'll set it equal to a table with the associated ID of that Game Pass.
I'll paste that there, and then I'm also going to give a name for my game pass.
I'll just call it the Knife Game Pass.
And then we need to do the same thing for our reload game pass as well.
Back in the Game Pass section we'll go ahead and create another new game Pass.
I'm going to call this one faster reload.
And I'm going to say something like.
This pass gives you a reload buff on all the guns in your inventory.
We'll just say something like that, and then we can go ahead and add an image to this game pass as
well.
Here I've just added a very simple and basic image for my game pass.
And then we can go ahead and hit Create Pass.
And then we'll go inside of here, go to the sales section, place it for sale and we'll add in our
price.
I'll just do 99 Robux, we'll hit save, and then we can go ahead and copy that asset ID.
And now back inside of studio, we'll create another new key inside of our enum.
We'll call this one our Reload Game Pass.
Set that equal to a table.
The ID is going to be the one we just copied, and the name I will call it my Reload Game Pass.
Okay, so now what I want to do is I want to create a new script inside of server script service.
And this script is going to be my game pass handler.
And we're going to be handling all of the events and prompting purchases for game passes inside of our
game, using the same common template as before.
We'll get rid of that section and we'll get rid of that section.
And then we can go ahead and grab the service that's responsible for prompting Game Pass purchases to
players, which is called the marketplace Service.
We'll get the marketplace service that's equal to game get service marketplace service.
And then we also want to grab the player service as well.
And what we want to go ahead and do is we want to listen for when a player joins our game.
So when a player is added, we'll connect a function and actually we'll create a dedicated function
for this.
We'll call it on player added.
And the purpose of this function is to check to see if the player owns any of the game passes that are
inside of our Game Pass enum.
So let's go ahead and grab Replicated storage.
And then we can go ahead and make a reference to our Game Pass enum.
So we'll require replicated storage, dot modules, dot enums, dot game pass enum.
And then we can connect our on player added function to this event, which will get passed a player.
And then we want to check if this player owns any of the game passes in our Game Pass enum.
So we're going to loop through every single game pass inside of our Game Pass enum.
And we want to check if this player actually owns it.
And the way we could do that is that inside of the marketplace service there is a function called user
owns Game Pass async and it says returns true if the player with the given user ID owns the game pass
with the given game pass ID.
Now, since this is an asynchronous function, we're going to have to wrap it in a p call.
So you know the deal.
We'll get our success and result variable and that's equal to p call.
We'll put a lambda function in there.
And then we're going to copy this.
And we're going to call the user owned Game Pass async function.
The user ID is going to be our player's user ID.
And then the game pass ID is going to be our game pass.id.
And then we can go ahead and return that at the end of our function.
And we can go ahead and check if we were successful with this pickle.
If we were not successful and an error occurred that was outside of our control, then we'll just print
something like error while attempting to check Game Pass status for player.
And then we can just put the error on a new line.
So we'll do backslash n and then concatenate that with the results from our p call.
Otherwise if we were successful and this function returned true so else if result then we can go ahead
and set an attribute on this player to let the entire game know hey, this player has this game pass.
So we're going to do player set attribute.
And we're going to be using the name of this game pass.
So we'll refer to our Game Pass and get the name and set that attribute to true on our player.
So now any script in our game can go ahead and check to see if this player has this attribute.
And if they have this game pass and then act accordingly.
Now one of those game passes was my golden knife.
Let's go ahead and actually set up our golden knife.
If we head to server storage and go into tools, we have our golden knife right here, but we haven't
scripted anything inside of it.
If I change the parent to the workspace and I go and find it, here's my golden knife.
It's literally the exact same knife, except it's made out of gold.
And what we should do with this knife is we should basically just copy all of these scripts that were
inside of our regular knife, including the event will copy that, paste it inside of our golden knife.
But this time we'll update the properties for the Golden knife to be more buffed like a better knife
to use, and it swings faster and deals more damage.
So I'll keep the damage the same.
But actually what I want to do is I want to increase the chance of a critical hit for my player.
And I'm going to above this a lot.
I'm going to make it a 55% chance of getting a critical hit.
And I'm also going to be increasing the critical hit multiplier.
So the minimum will bump to like 1.4.
And then the max we can bump to like 2.2.
And then I don't want to impose any swing cooldowns.
So I'll set this value to zero.
And then I also want to decrease the duration of the animation as well.
So we'll set this to like 0.25 seconds.
So now we have a faster swinging knife that has a better chance of dealing critical hits and dealing
more damage.
So I'll go ahead and move my golden knife back inside of server storage.
And now what we can do inside of our game pass handler is we can go ahead and listen for when a player
has a character added to them.
And then we can go ahead and check to see if the player is on the live team, and if they are, we'll
give them this golden knife.
So I'll create a function I'm going to call it on character added.
And we'll get past a character to this function.
And then with this player inside of the on player added event, what we're going to do is we're going
to connect to their character added event.
So we'll connect.
Our on character added function to this event.
And then inside of here we're going to get the player from the players.
Um, get player from character function.
So player is going to be equal to players.
Get player from character.
Pass the character here.
And then we can go ahead and check to see if this player has the game pass the knife game pass.
So if player get attribute and then we're going to use Game Pass enum dot knife game Pass.
And we're going to check to see if this player owns the knife game pass.
And if they do then the next thing we need to check is if the player is on the alive team.
So if player dot team is equal to the alive team, let's go ahead and grab the team service.
So if their team is equal to teams alive, then let's go ahead and give them the golden knife.
So we're also going to need server storage.
Server storage.
And we'll go ahead and make a clone of server storage tools.
Get the Golden knife, clone that, and then we'll set the parent of that clone equal to the player's
backpack.
So now if I play the game, since I'm the owner of the game, I'm automatically going to have or own
all of the game passes, which means I should spawn with a golden knife inside of my inventory.
So let's go ahead and play the game.
And what I'm going to do is I'm actually going to head over to the player service and look at my character.
And unfortunately, we don't have any attributes set on me, which is kind of interesting.
If I spawn it to the map, I did not get my golden knife, which is strange.
So let's go ahead and figure out why that's the case.
I think it could be because we're testing in studio.
The player might be added before the server is able to listen to the player added event.
So just as a little bit of extra security, what I'm going to do is I'm going to loop through every
player that's already in the game.
So we'll do players, get players.
And that way, if there's any players in the game that weren't able to be listened to because the player
added event did not have this function connected to it yet, then we can go ahead and call our on player
added function and pass our player to it.
And then one last thing I want to make a minor change to is that since this is going to be yielding
right here, I don't want to halt the main thread of execution and have it stuck yielding.
So I'm actually going to spawn in a new thread.
This code right here.
So I'll do that.
So that way for every single game pass we're checking, we are doing them all instantaneously at the
same time for a player.
Instead of having to sequentially go from one game pass to the next game pass, having to wait and yield
for this function to return to us a result.
So we're going to try it this way.
And now if we go and play test the game.
Hopefully if we go and take a look at our player.
We still don't have the attributes.
Very weird.
Okay, so I found out what the issue was, which is a very strange issue.
If I go to my knife game pass and I copy the asset ID directly from here, this is the ID that it gives
me, right?
We pasted it into our module script.
However, if I go back and I copy the asset ID from here, take a look at this.
The ID is completely different.
And this is the ID that actually works.
The other IDs were not working.
Why this is the case?
I have no idea.
It must be a very weird bug.
So what I advise for you to do is to go back to your game passes and copy the asset ID from here and
not from here.
I don't know why it's giving me two different asset ID numbers.
That's very weird, but go ahead and copy your asset IDs from here and then it should be working.
Okay, I just updated the two IDs for my game pass.
They're completely different from the other ones I copied.
I don't know why Roblox moment, but now if we go and play test our game and then we go back to my player,
there we go.
Now it says that I own both the knife game pass and the reload game pass, and if I go and play test
my game, there we go.
I get spawned with the Golden knife.
Very cool.
Okay, the next game pass that I want to script for is going to be the faster reload game pass.
And this one's going to be a little bit trickier, because what we need to do is we need to update the
properties module script for our gun on both the client and on the server.
So that means if the server finds that a player has a gun in their inventory, the server needs to update
the reload duration on the server side and then tell the client to update the reload duration on their
side as well, because again, the module scripts ones on the server, ones on the client, they're
going to be two different module scripts that both need to be updated.
So in order to account for that, we can use the exact same gun event that the guns use and instead
fire to a client to a specific gun that needs to be updated with its reload duration.
And then we can listen from the local script that is inside of our gun.
When the server tells us to update the reload duration, we'll do that on the client side, and then
the server updates the reload duration on the server side as well.
So that means what I want to do is I want to check if my player.
Get attribute.
They have the faster reload.
So reload game pass.
If they own that game pass then we want to listen for when a child is added to the player's character.
And the reason for that is we need to check if that child is a gun, and if it is, we want to tell
the client to update the reload duration property for that particular gun.
So.
When the character has a child added to them.
We're going to connect a function to this which is going to be on, child added.
So we'll create a new function, call it on, child added.
We'll get past the child and we need to check to see if this child is a tool.
So if this child is not a tool, is a tool then we're going to return.
If this child is a tool, but it's not a gun, then we're also going to return.
So if not child get attribute gun type then we also need to return.
And then another thing we need to keep track of is if we've already buffed the reload duration for this
particular gun.
So what we can go ahead and do is set an attribute on this child.
Once the server has a buffed the reload duration and set to say something like it's already been reload
buffed.
So that way when the player equips the tool and then re equips it, we don't accidentally buff the reload
duration again on the gun.
So what we can go ahead and do is set an attribute on this gun.
And we're going to call it something like reload buffed.
And we'll set that to true.
And that way we can go ahead and check if this child already has the attribute of reload buffed.
And if it does, then we're going to return.
Otherwise we can go ahead and get the player that has this gun equipped.
So we're going to do players get player from character.
And that's going to be the parent of this child.
And then we're going to grab the properties for this gun.
So we'll require.
Child that properties since it's a gun.
And then we can go ahead and update the properties reload duration.
And since we want to make the reload duration 35% faster, let's go ahead and define a constant up here.
And I'll call this constant reload percent.
And we're going to set it to 0.65.
And then we can go ahead and multiply our reload duration by this value to make the reload duration
35% faster.
So we'll do times equal reload percent.
And then here we could use the gun event that's inside of replicated storage to tell this player, hey,
you need to update the property for this particular gun on your side as well.
So let's go ahead and make a reference to that gun event.
So replicated storage dot remotes dot gun event.
And I want to hop into my gun comms enum, and then I want to create a section for actions to be given
to the client.
And this action I'm going to call it Update property.
So that way the client knows to update a property on their gun and then back inside of our game pass
handler we can go ahead and grab the gun comms enum, so we'll require replicated storage, dot modules,
dot enums, dot gun comms enum.
And then we'll use the gun event fire to this particular player.
So we'll pass the player here.
We'll give them the action which is going to be gun comms enum dot two client dot update property.
And we also want to let them know which particular gun they need to update.
And that's because if the player has multiple different guns, then all of those guns are going to be
listening to this event.
So we only want to fire this to a particular gun in their inventory.
And the easiest way for us to do that is simply just to pass the tool itself to the player.
So the player knows exactly which gun to update.
And then we could pass the property.
They need to update on that gun, which would be the reload duration, and then we can tell them what
value we would like them to set that reload duration to.
And that's just going to be equal to the reload duration that is on the server.
But now what we need to do is we need to hop into one of the local scripts for our gun.
I'll just do it for the AR, and then we'll go down to the handler section, and we want to listen for
when our gun event is fired on the client.
So on client event we'll connect a function to this.
And the server is going to be passing to us the action.
And then they're going to pass us the particular gun they want us to update.
So we'll call this passed gun the property.
And then the value we want to update to that property.
So first thing we want to check is if this passed gun the server is giving to us is equal to the same
gun that this local script is in.
So if the passed gun is not equal to the gun that's referred to in this local script, then we're just
going to return and ignore it for this particular gun.
Otherwise we can check if the action is equal to the gun.
Comms enum of two client.
Dot update property, and if it is, then we can just simply refer to the properties inside of our gun
and update this particular property the server wants us to update with this new value.
And just like that, we should now have implemented a reload buff to all of the guns in our game.
So what I'm going to do is I'm going to copy this new local script and put it inside of all of my guns,
and I'll go ahead and get rid of the old local script for my guns.
So we'll just delete that old one, get rid of that one, that one.
Delete, delete and delete.
And then just to quickly test this out, I'm going to copy the R and put it inside of the starter pack.
And then to try to make this reload duration as prominent as possible.
So we can tell to see if the reload buff got applied to us.
I'm going to set the reload percent to like one.
So our reload duration should be like 90% faster.
So let's go ahead and see if that worked.
If we play the game.
And then we go and hop into the game.
I got my assault rifle, and if I shoot and then reload.
Yeah, you can see our reload duration was much faster.
Let's try that again.
And as you can see, look how fast reload is.
Obviously that's a reload duration.
That's too fast for my taste.
I much prefer the 35% buff, but at least we know that the reload buff is actually working for any players
in our game that have the Reload Buff game pass.
So the next thing that we need to go ahead and do is we need to script the functionality for the player
to interact with the GUI, to buy game passes, and then we need to listen on the server when the player
actually purchases those game pass.
And if they do purchase it, we need to set those attributes on our player to true in real time, because
we don't want to force our player to have to rejoin the game in order to get their benefits.
So let's go ahead and go back into the local script for our starting menu.
We'll open that up.
And then we want to go ahead and listen to all the stuff that's going to be inside of our shop.
Specifically, when the player presses the shot button, we want to display the shop onto their screen,
and when they press the close button, we want to close the shop.
And if they press one of the buy buttons for one of the game passes, then we'll fire to the server.
Hey, we want to purchase this particular game Pass, so let's actually go ahead and grab the Game Pass
enum here in this local script will require and get and replicated storage modules dot enums dot game
pass enum.
And then we'll go down to our handlers section, and we'll make a little section here for listening
to events for our shop.
And I want to kind of segregate it and be able to collapse it and hide it, just to make my script more
organized.
And the easiest way to do that would be to create a new scope.
And the easiest way to create a new scope would just be to type du and then hit enter.
And what I've done right here is just made a little new scope that I'm able to collapse.
And any variables I make inside of this scope.
For example, this is a variable right here since it's local to this particular scope right here, I
can't access the example variable outside of that scope.
So inside of my little scope, I want to listen for when my shot button is activated.
And when that happens, we want to go ahead and make the shot frame visible on the player screen.
And then inside of our shop frame we have a close button.
We want to listen for when that is activated and when the player presses that.
We'll go ahead and refer to our shop frame and set visible back to false.
And then inside of the shop frame, we have our container frame that contains all of the different frames
for the game passes.
For example, one of them is going to be our faster reload frame, and inside of there we have a buy
button.
And we'll go ahead and listen for when that is activated and when it is.
This is where we could fire an event to the server to prompt a purchase to us.
So inside of replicated storage, I have another remote event inside of the GUI folder called Buy Game
Pass.
Let's go ahead and make a reference to that real quick.
I'll create a new variable.
I'll call it Game Pass Event and that's replicated storage, dot remotes, dot guy dot game pass or
by Game Pass.
And then we can go ahead and use this Game Pass event and fire to the server.
And then we can tell them which game pass we would like to purchase by passing the ID of the Game Pass.
So we'll use our Game Pass enum.
And we'll use for this case.
It's going to be the reload game pass and we'll just pass the ID to the server.
And I'm going to copy this, paste this here.
And we want to do the same thing for the Golden Knife Game Pass.
And this time we're going to tell the server that we would like to purchase the Knife Game Pass.
So now what we need to do on the server is listen for when this Game Pass event is fired.
And when the player tells us they want to purchase a game pass, we're going to prompt a purchase to
them.
The backhand side of our game pass handler.
Well, we can go ahead and do is we can listen for when our Game Pass event is fired.
And that means we're actually going to need to make a variable for it.
So we'll get our Game Pass event that's replicated storage dot events or remotes GUI dot.
Game pass or buy.
Game pass.
There we go.
And then Game Pass event will listen for on server event, connect a function, get the player and then
the ID of the game pass they want to purchase.
And then what we want to go ahead and do is we want to loop through all of the game passes in our enum
and check to see if the ID the player passed to us actually belongs to one of the game passes in our
Game Pass enum.
So for every single game pass inside of our Game Pass enum, what we want to do is we want to check
if this game pass ID, so if game pass ID if it's not equal to this game passes.
Uh, ID then we'll just continue to the next game pass.
Otherwise, if we found a matching game pass, then we can go ahead and use the marketplace service.
And there's a function in there called Prompt Game Pass purchase.
And we need to pass the player and then the ID for the game pass.
So we'll pass our player here.
And then we can go ahead and pass the game pass.id.
And once we do that, we can go ahead and just break out of this loop because there's no reason for
us to continue looping through the other game passes because we found the one that the player wanted
to purchase.
So when we call this function on the client side, a little pop up window is going to appear to tell
them to purchase the Game Pass.
And if they purchase it, then it's going to notify us on the server and there's an event for that.
There is an event inside of the marketplace service called Prompt Game Pass Purchase finished.
So we're going to connect a function to this.
And this function is going to be passed to the player what the game pass ID was and whether or not they
purchased the game pass.
So we'll get the player the ID of the game pass, and then it'll tell us whether or not it was purchased.
So now what we can go ahead and do is we can again loop through all of the game passes in our Game Pass
enum.
And if this ID is not equal to this game pass ID, then we'll just continue looping to the next game
pass until we eventually find which game pass they purchased.
And if we've confirmed that they've purchased the Game Pass, then we can go ahead and set an attribute
on this player for this particular game Pass.
And we'll just use the Game Pass dot name and set that equal to true.
And of course we only want to do this if they actually purchased the Game Pass.
So if they did not purchase the Game Pass then we're just going to return and ignore this player.
Otherwise if they did purchase the game pass, then we're going to set that attribute on our player
to true.
And then because we're setting that attribute on them, any time they spawn into the game, we're going
to be giving them their golden knife or any time they have a gun added to their inventory.
If it's the reload game pass, we're going to be buffing the reload for them.
So let's go ahead and test to see if all of this is working.
We'll go and play test our game.
And we should be able to open up our store if we hit this button.
There we go.
Our store is open.
We have our golden knife and our fast reload.
I didn't upload any images for these two frames.
If you want to go ahead and insert your own images inside of the GUI, you're more than welcome to do
that.
But we want to test if the server is going to prompt us to purchase the Game Pass.
So if I hit this buy button.
There we go.
It says you already own this item.
Your account has not been charged.
Which is, of course, what I would expect because I already own the Game pass.
But as you can see, it is working when we press these buy buttons.
You already own this item.
Your account has not been charged, so we're not able to purchase them because it's like, what are
you doing?
You already you already own the game pass, right?
And if we go and playtest our game, I've got my golden knife ready to slay some zombies.
So let's go ahead and actually test out our golden knife.
This thing should be a lot better than the regular knife.
So if I stab this guy, hopefully I get a critical hit here.
It also swings a lot faster than the regular knife.
So if I swing the regular knife, that's how fast I can swing it.
And then with the golden knife, as you can see, I can swing it a lot faster and it does deal a lot
more damage.
Yeah.
Of course, you can further buff the damage and the critical hit rate of this golden knife.
Do whatever you want, change your game however you want.
It's totally up to your creative preference.
Let's go ahead and clear out all these zombies.
I got a one hit shot on that zombie right there.
Oh, it looks like I forgot to reset the value back to one.
So it says game over.
You win.
So I need to actually go back.
And it killed me.
I need to go back to my game handler and make sure I actually reset the total waves back to 11.
And then I'm going to reset the intermission back to its regular value of 60, and then the start intermission
back to its value of 30.
Otherwise.
That is how we can implement game passes into our game.
I hope you're enjoying the project so far and I'll see you in the next lecture.